package BTconn;

import java.io.IOException;
import java.util.Vector;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Display;

/*
 * Class responsible for detecting bluetooth device(s) and connecting to them
 * @author m4rt1n
 */
public class GpsBtController implements DiscoveryListener {

    /**
     * An instance of a Discovery Agent class
     */
    public DiscoveryAgent dA;

    /**
     * An instance of a Local Device class
     */
    public LocalDevice ld = null;

    /**
     * String containing local device's friendly name
     */
    private String fname = null;

    /**
     * String containing name of found single device
     */
    public String devName = null;

    /**
     * Vector containing BT Devices' addresses
     */
    private Vector address = null;

    /**
     * Vector containing remote devices
     */
    private Vector remoteDevices = null;

    /**
     * Vector containing devices services
     */
    private Vector services = null;

    /**
     * Number of discovered devices
     */
    private int numDevice = 0;

    /**
     * Boolean value if the device was found
     */
    public boolean devDiscovered = false;

    /**
     * Boolean value if the service was found
     */
    public boolean serviceDiscovered = false;

    /**
     * Boolean value if the inquiry is completed
     */
    public boolean inquiryCompleted = false;

    /**
     * Boolean value if the service search is completed
     */
    public boolean serviceSearchCompleted = false;

    /**
     * URL of a service
     */
    public String serviceURL = null;

    public UUID[] UUIDs = new UUID[1];
    static int newuuid = 0;

    public String[] devNames = null;

    public String[] serviceNames = null;

    public String connectionURL = null;

    public int transID;


    private void initBluetooth()
    {
        try
        {
            ld = LocalDevice.getLocalDevice();
            ld.setDiscoverable(DiscoveryAgent.GIAC);
            dA = ld.getDiscoveryAgent();
        }
        catch (BluetoothStateException ex)
        {
            ex.printStackTrace();
            System.err.println("Failed to initialize Bluetooth in gbc constructor!!");
        }
        remoteDevices = new Vector();
    }

    /**
     * Constructor that initializes Bluetooth and sets DiscoveryListener
     * @param dl instance of DiscoveryListener
     */
    public GpsBtController(DiscoveryListener dl)
    {
        listener = dl;
        initBluetooth();
    }

    /**
     * Constructor that initializes Bluetooth
     * It does not set DiscoveryListener
     */
    public GpsBtController()
    {
        listener = null;
        initBluetooth();
    }

    private DiscoveryListener listener;

    private void notifyDeviceDiscovered(RemoteDevice rd , DeviceClass dc)
    {
        if(listener!=null)
            listener.deviceDiscovered(rd , dc);
    }

    private void notifyInquiryCompleted(int dType)
    {
        if(listener!=null)
            listener.inquiryCompleted(dType);
    }

    private void notifyServicesDiscovered(int transID, ServiceRecord[] sR)
    {
        if(listener!=null)
            listener.servicesDiscovered(transID, sR);
    }

    private void notifyServiceSearchCompleted(int transID, int respCode)
    {
        if(listener!=null)
            listener.serviceSearchCompleted(transID, respCode);
    }

    /**
     * Method triggered by the Controler class
     * when the device is found in range
     */
    public void deviceDiscovered(RemoteDevice rd , DeviceClass dc)
    {
        try
        {
            //Thread.sleep(1000);
            System.err.println(rd.toString() + rd.getFriendlyName(true));
            //address.addElement(rd.getBluetoothAddress());
            addRemoteDevice(rd);
            devDiscovered = true;

            //setDiscoveredDevName(rd);
        }
        catch (Exception e)
        {
            System.err.println("Failed to add device to a Vector - remoteDevices!!!");
        }
        System.out.println("Device has been discovered!");
        notifyDeviceDiscovered(rd, dc);
    }

    /**
     * Method triggered by the Controler class
     * when the searching for devices is finished
     */
    public void inquiryCompleted(int dType)
    {
        inquiryCompleted = true;
        notifyInquiryCompleted(dType);

        if(dType==INQUIRY_COMPLETED)
            System.out.println("inquiry is completed!");
        else if(dType==INQUIRY_TERMINATED)
            System.out.println("inquiry is terminated!");
        else if(dType==INQUIRY_ERROR)
            System.out.println("inquiry error!");
    }

    /**
     * Method triggered by the Controler class
     * when the service of a device is discovered
     */
    public void servicesDiscovered (int transID, ServiceRecord[] sR)
    {
//        for (int i=0; i<sR.length; i++)
//        {
            addService(sR);
            
//        }
        serviceDiscovered = true;
        notifyServicesDiscovered(transID, sR);
        System.out.println("Found le service!");
    }

    /**
     * Method triggered by the Controler class
     * when the searching for services is finished
     */
    public void serviceSearchCompleted(int transID, int respCode)
    {
       
        serviceSearchCompleted = true;
        setConnectionURL(services, 0);
//        for (int i=0; i<services.size(); i++)
//        {
//
//            connectionURL = services.elementAt(i).getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);
//        }
        System.out.println("Service search is completed!");
        System.out.println(remoteDevices.elementAt(0).toString());
        notifyServiceSearchCompleted(transID, respCode);
    }

    /**
     * Adds the found remote device to a Vector
     */
    public void addRemoteDevice(RemoteDevice rd)
    {
        remoteDevices.addElement(rd);
            System.err.println("remote devices: " + (remoteDevices==null ? "nima" : "rdlen: " + remoteDevices.size()));
        numDevice++;
    }

    public void resetRemoteDevices()
    {
        remoteDevices.removeAllElements();
    }

    public void addService(ServiceRecord[] sR)
    {
        services.addElement(sR);
    }

    public void setConnectionURL(Vector services, int num)
    {
        if(services!=null)
        {
            ServiceRecord service = (ServiceRecord)services.elementAt(num);
            connectionURL = service.getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);
        }
        else
        {
            System.err.println("Services are null!");
        }
        
    }

    public String getConnectionURL()
    {
        return connectionURL;
    }

    public void setDiscoveredDevName(RemoteDevice rd)
    {
        try
        {
            devName = rd.getFriendlyName(false);
        }
        catch (IOException ex)
        {
            ex.printStackTrace();
        }
    }

    public String getDiscoveredDevName()
    {
        return devName;
    }

    /**
     * Returns the Vector with remote devices
     */
    public Vector getRemoteDevices()
    {
        return remoteDevices;
    }

    public String getRemoteDeviceName(int id)
    {
        return remoteDevices.elementAt(id).toString();
    }

    /**
     * Returns how many devices were found
     */
    public int getNumberOfDevices()
    {
        return numDevice;
    }

    public void resetNumberOfDevices()
    {
        numDevice = 0;
    }

    /**
     * Returns the String[] with remote devices' friendly names
     */
    public String[] getDeviceNames()
    {
        devNames = new String[remoteDevices.size()];
        for(int i=0; i<remoteDevices.size(); i++)
        {
            try
            {
                devNames[i] = ((RemoteDevice) (remoteDevices.elementAt(i))).getFriendlyName(false);
            } 
            catch (IOException ex)
            {
                ex.printStackTrace();
                System.err.println("Probably no devices were found!");
            }
        }
        return devNames;
    }

    public String[] resetDeviceNames()
    {
        devNames = new String[0];
        return devNames;
    }

    public String[] getServiceNames()
    {
        //System.out.println("SERWISUF JEZD "+ services.size());
        if(services!=null)
        {

            serviceNames = new String[services.size()];
            for(int i=0; i<services.size(); i++)
            {
                serviceNames[i] = services.elementAt(i).toString();
            }
        }
        else
        {
            serviceNames = null;
        }
        return serviceNames;
    }

    public String[] resetServiceNames()
    {
        serviceNames = new String[0];
        return serviceNames;
    }

    /**
     * Returns if the device is discovered
     */
    public boolean isDevDiscovered()
    {
        return devDiscovered;
    }

    /**
     * Returns if the inquiry is completed
     */
    public boolean isInquiryCompleted()
    {
        return inquiryCompleted;
    }
    
    public boolean isServiceDiscovered()
    {
        return serviceDiscovered;
    }

    public boolean isServiceSearchCompleted()
    {
        return serviceSearchCompleted;
    }

    /**
     * Returns friendly name of a local device
     */
    public String getLocalFriendlyName()
    {
        return fname = ld.getFriendlyName();
    }

    /**
     * Starts the searching of BT devices
     */
    public void search4Devices()
    {
        devDiscovered = false;
        inquiryCompleted = false;

        try
        {
            dA.startInquiry(DiscoveryAgent.GIAC, this);
        }
        catch (BluetoothStateException ex)
        {
            ex.printStackTrace();
            System.err.println("Failed to initialize Bluetooth after refreshing devices list");
        }
    }

    public void search4Services(int id)
    {
        System.out.println("SEARCHING FOR SERVICES!!!!!!!!!");
        serviceDiscovered = false;
        serviceSearchCompleted = false;
        UUIDs[0] = new UUID(newuuid++);
        transID=500;

        try
        {
            RemoteDevice remoteDevice = (RemoteDevice)remoteDevices.elementAt(id);
            System.out.println("TUKEJ?");
            //int i = 1;
                transID = dA.searchServices(null,UUIDs,remoteDevice,this);
            System.out.println(remoteDevice);
        }
        catch (BluetoothStateException bse)
        {
            bse.printStackTrace();
            System.err.println("COS JEST NIEHALO BluetoothStateException");
        }
        catch (IllegalArgumentException iae)
        {
            iae.printStackTrace();
            System.err.println("COS JEST NIEHALO IllegalArgumentException");
        }
        catch (NullPointerException npe)
        {
            npe.printStackTrace();
            System.err.println("COS JEST NIEHALO NullPointerException");
        }

//        try
//        {
//            dA.searchServices(null, UUIDs, rd, this);
//        }
//        catch (BluetoothStateException bse)
//        {
//            bse.printStackTrace();
//        }
    }
}

